package com.hechuan.interceptor;

import com.baomidou.mybatisplus.core.toolkit.PluginUtils;
import com.baomidou.mybatisplus.extension.plugins.inner.InnerInterceptor;
import net.sf.jsqlparser.JSQLParserException;
import net.sf.jsqlparser.expression.Expression;
import net.sf.jsqlparser.expression.Parenthesis;
import net.sf.jsqlparser.expression.StringValue;
import net.sf.jsqlparser.expression.operators.conditional.AndExpression;
import net.sf.jsqlparser.expression.operators.conditional.OrExpression;
import net.sf.jsqlparser.expression.operators.relational.EqualsTo;
import net.sf.jsqlparser.parser.CCJSqlParserUtil;
import net.sf.jsqlparser.schema.Column;
import net.sf.jsqlparser.statement.Statement;
import net.sf.jsqlparser.statement.select.PlainSelect;
import net.sf.jsqlparser.statement.select.Select;
import net.sf.jsqlparser.statement.select.SelectBody;
import org.apache.ibatis.executor.Executor;
import org.apache.ibatis.mapping.BoundSql;
import org.apache.ibatis.mapping.MappedStatement;
import org.apache.ibatis.session.ResultHandler;
import org.apache.ibatis.session.RowBounds;

/**
 * 查询拦截器6
 */
public class QueryInterceptor6 implements InnerInterceptor {

    /**
     * 优雅的拼接sql
     */
    @Override
    public void beforeQuery(Executor executor, MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, BoundSql boundSql) {
        // 原始sql：SELECT  id,name,age,address  FROM t_user WHERE age = 18
        String originSql = boundSql.getSql();
        System.out.println("originSql：" + originSql);

        // 获取 Statement 执行sql的对象
        Statement statement = null;
        try {
            statement = CCJSqlParserUtil.parse(originSql);
        } catch (JSQLParserException e) {
            throw new RuntimeException(e);
        }

        Select select = (Select) statement;

        SelectBody selectBody = select.getSelectBody();
        if (selectBody == null) {
            return;
        }

        String targetSql = "";
        if (selectBody instanceof PlainSelect) {

            PlainSelect plainSelect = (PlainSelect) selectBody;
            Expression where = plainSelect.getWhere();

            // name = '张三'
            EqualsTo usesEqualsTo1 = new EqualsTo();
            usesEqualsTo1.setLeftExpression(new Column("name"));
            usesEqualsTo1.setRightExpression(new StringValue("张三"));

            // name = '赵六'
            EqualsTo usesEqualsTo2 = new EqualsTo();
            usesEqualsTo2.setLeftExpression(new Column("name"));
            usesEqualsTo2.setRightExpression(new StringValue("赵六"));

            // name = '张三' or name = '赵六'
            OrExpression orExpression = new OrExpression();
            orExpression.setLeftExpression(usesEqualsTo1);
            orExpression.setRightExpression(usesEqualsTo2);

            // (name = '张三' or name = '赵六')
            Parenthesis parenthesis = new Parenthesis();
            parenthesis.setExpression(orExpression);

            // ... AND (name = '张三' or name = '赵六')
            AndExpression andExpression = new AndExpression(where, parenthesis);
            // 将新的where条件sql 设置回去
            plainSelect.setWhere(andExpression);

            // 期望得到的sql：SELECT id, name, age, address FROM t_user WHERE age = ? AND (name = '张三' OR name = '赵六')
            targetSql = plainSelect.toString();
            System.out.println("targetSql：" + targetSql);
        }

        // 修改完成的sql 再设置回去
        PluginUtils.MPBoundSql mpBoundSql = PluginUtils.mpBoundSql(boundSql);
        mpBoundSql.sql(targetSql);
    }

}
